/*
 * StartApplication.java
 *
 * Created on October 8, 2006, 12:15 AM
 */

package org.sunspotworld;

import com.sun.spot.core.resources.transducers.ISwitch;
import com.sun.spot.core.resources.transducers.ITriColorLED;
import com.sun.spot.core.resources.transducers.LEDColor;
import com.sun.spot.edemo.EDemoBoard;
import com.sun.spot.ipv6.util.Mutex;
import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;

/**
 * The startApp method of this class is called by the VM to start the
 * application.
 *
 * The manifest specifies this class as MIDlet-1, which means it will
 * be selected for execution.
 */
public class SunSpotApplication extends MIDlet {
    private ITriColorLED [] leds = EDemoBoard.getInstance().getLEDs();
    private ISwitch sw1 = EDemoBoard.getInstance().getSwitches()[0];
    private ISwitch sw2 = EDemoBoard.getInstance().getSwitches()[1];
    private byte demo = 0;
    private Thread tRed;
    private Thread tBlue;
    private Thread tGreen;
    private boolean running;

    private Mutex mutex = new Mutex();

    private void flashBlue(boolean [] flashLED, long millis) {
        LEDColor color = new LEDColor(0,0,0);
        for (int i=0; i<8; i++) {
            if(flashLED[i]) {
                color = leds[i].getColor();
                color.setBlue(100);
                leds[i].setColor(color);
                leds[i].setOn();
            }
        }
        pause(millis);
        for (int i=0; i<8; i++) {
            if(flashLED[i]) {
                color.setBlue(0);
                leds[i].setColor(color);
            }
        }
    }

    private void flashRed(boolean [] flashLED, long millis) {
        LEDColor color = new LEDColor(0,0,0);
        for (int i=0; i<8; i++) {
            if(flashLED[i]) {
                color = leds[i].getColor();
                color.setRed(100);
                leds[i].setColor(color);
                leds[i].setOn();
            }
        }
        pause(millis);
        for (int i=0; i<8; i++) {
            if(flashLED[i]) {
                color.setRed(0);
                leds[i].setColor(color);
            }
        }
    }

    private void flashGreen(boolean [] flashLED, long millis) {
        LEDColor color = new LEDColor(0,0,0);
        for (int i=0; i<8; i++) {
            if(flashLED[i]) {
                color = leds[i].getColor();
                color.setGreen(100);
                leds[i].setColor(color);
                leds[i].setOn();
            }
        }
        pause(millis);
        for (int i=0; i<8; i++) {
            if(flashLED[i]) {
                color.setGreen(0);
                leds[i].setColor(color);
            }
        }
    }

    private void syncedFlashBlue(boolean [] flashLED, long millis) {
        synchronized (leds) {
            flashBlue(flashLED, millis);
        }
    }

    private void syncedFlashRed(boolean [] flashLED, long millis) {
        synchronized (leds) {
            flashRed(flashLED, millis);
        }
    }

    private void syncedFlashGreen(boolean [] flashLED, long millis) {
        synchronized (leds) {
            flashGreen(flashLED, millis);
        }
    }

    private void mutexFlashBlue(boolean [] flashLED, long millis) {
        mutex.lock();
        flashBlue(flashLED, millis);
        mutex.unlock();
    }

    private void mutexFlashRed(boolean [] flashLED, long millis) {
        mutex.lock();
        flashRed(flashLED, millis);
        mutex.unlock();
    }

    private void mutexFlashGreen(boolean [] flashLED, long millis) {
        mutex.lock();
        flashGreen(flashLED, millis);
        mutex.unlock();
    }

    private void respondToSwitches() {
        while (true) {
            pause(100);
            if (sw1.isClosed()) {
                running = false;
                try {
                    tRed.join();
                    tBlue.join();
                    tGreen.join();
                } catch (InterruptedException e) {}
                demo = (byte)((demo + 1)%4);
                switch (demo) {
                    case 0:
                        initialize1();
                        break;
                    case 1:
                        initialize2();
                        break;
                    case 2:
                        initialize3();
                        break;
                    case 3:
                        initialize4();
                        break;

                }
                running = true;
                try {
                    if(!tRed.isAlive()) {
                        tRed.start();
                    }
                    if (!tBlue.isAlive()) {
                        tBlue.start();
                    }
                    if (!tGreen.isAlive()) {
                        tGreen.start();
                    }
                } catch (IllegalThreadStateException e) {}
                while(sw1.isClosed()) pause(100);
            }
            if (sw2.isClosed()) {

            }
        }
    }

    private void initialize1() {
        tRed = new Thread() {
            public void run() {
                boolean [] flash = {true, true, true, false, false, false, false, false};
                while (running) {
                    flashRed( flash, 500);
                    pause(500);
                }
            }
        };
        tBlue = new Thread() {
            public void run() {
                boolean [] flash = {false, false, false, true, true, true, false, false};
                while (running) {
                    flashBlue( flash, 300);
                    pause(300);
                }
            }
        };
        tGreen = new Thread() {
            public void run() {
                boolean [] flash = {false, false, false, false, false, false, true, true};
                while (running) {
                    flashGreen( flash, 275);
                    pause(525);
                }
            }
        };

    }

    private void initialize2() {
        tRed = new Thread() {
            public void run() {
                boolean [] flash = {true, true, true, true, true, true, true, true};
                while (running) {
                    flashRed( flash, 500);
                    pause(500);
                }
            }
        };
        tBlue = new Thread() {
            public void run() {
                boolean [] flash = {true, true, true, true, true, true, true, true};
                while (running) {
                    flashBlue( flash, 300);
                    pause(300);
                }
            }
        };
        tGreen = new Thread() {
            public void run() {
                boolean [] flash = {true, true, true, true, true, true, true, true};
                while (running) {
                    flashGreen( flash, 275);
                    pause(525);
                }
            }
        };

    }

    private void initialize3() {
        tRed = new Thread() {
            public void run() {
                boolean [] syncedFlash = {true, true, true, true, true, true, true, true};
                while (running) {
                    syncedFlashRed( syncedFlash, 500);
                    pause(500);
                }
            }
        };
        tBlue = new Thread() {
            public void run() {
                boolean [] syncedFlash = {true, true, true, true, true, true, true, true};
                while (running) {
                    syncedFlashBlue( syncedFlash, 300);
                    pause(300);
                }
            }
        };
        tGreen = new Thread() {
            public void run() {
                boolean [] syncedFlash = {true, true, true, true, true, true, true, true};
                while (running) {
                    syncedFlashGreen( syncedFlash, 275);
                    pause(525);
                }
            }
        };

    }

    private void initialize4() {
        tRed = new Thread() {
            public void run() {
                boolean [] syncedFlash = {true, true, true, true, true, true, true, true};
                while (running) {
                    mutexFlashRed( syncedFlash, 500);
                    pause(500);
                }
            }
        };
        tBlue = new Thread() {
            public void run() {
                boolean [] syncedFlash = {true, true, true, true, true, true, true, true};
                while (running) {
                    mutexFlashBlue( syncedFlash, 300);
                    pause(300);
                }
            }
        };
        tGreen = new Thread() {
            public void run() {
                boolean [] syncedFlash = {true, true, true, true, true, true, true, true};
                while (running) {
                    mutexFlashGreen( syncedFlash, 275);
                    pause(525);
                }
            }
        };
    }

    /**
     * Pause for a specified time.
     *
     * @param time the number of milliseconds to pause
     */
    private void pause (long time) {
        try {
            Thread.currentThread().sleep(time);
        } catch (InterruptedException ex) { /* ignore */ }
    }

    protected void startApp() throws MIDletStateChangeException {
        initialize1();
        running = true;
        tRed.start();
        tBlue.start();
        tGreen.start();
        respondToSwitches();
    }

    protected void pauseApp() {
        // This will never be called by the Squawk VM
    }

    protected void destroyApp(boolean arg0) throws MIDletStateChangeException {
        // Only called if startApp throws any exception other than MIDletStateChangeException
    }
}
